import 'dart:io';

import 'package:cher_flare/modules/login/models/ly_login_info_manager.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import '../config/config.dart';
import 'http_config.dart';
import 'http_exception.dart';
import 'http_interceptor.dart';
import 'http_response_data.dart';

class HttpUtils {
  static final HttpUtils _instance = HttpUtils._internal();
  static HttpUtils get getInstance => _instance;
  late final Dio dio;

  final CancelToken _cancelToken = CancelToken();

  HttpUtils._internal() {
    dio = Dio(_baseOptions);
    dio.interceptors.addAll([HttpInterceptors()]);
  }

  /// 取消请求
  void cancelRequests({CancelToken? token}) {
    if (token != null) {
      token.cancel("cancelled");
    } else {
      _cancelToken.cancel('cancelled');
    }
  }

  static final BaseOptions _baseOptions = BaseOptions(
      baseUrl: HttpConfig.baseUrl,
      receiveTimeout: const Duration(milliseconds: HttpConfig.receiveTimeout),
      connectTimeout: const Duration(milliseconds: HttpConfig.connectTimeout),
      headers: {},
      contentType: "application/json");

  Future<HttpResponseData> get<T>(String path,
      {Map<String, dynamic>? queryParameters,
      bool? isShowHud,
      Options? options,
      CancelToken? cancelToken,
      ProgressCallback? onReceiveProgress}) {
    return _request<T>(path,
        queryParameters: queryParameters,
        isShowHud: isShowHud,
        options: checkOptions('GET', options),
        onReceiveProgress: onReceiveProgress,
        cancelToken: cancelToken);
  }

  Future<HttpResponseData> post<T>(String path,
      {data,
      Map<String, dynamic>? queryParameters,
      bool? isShowHud,
      Options? options,
      CancelToken? cancelToken,
      ProgressCallback? onsendProgress,
      ProgressCallback? onReceiveProgress}) {
    return _request<T>(
      path,
      data: data,
      options: checkOptions('POST', options),
      queryParameters: queryParameters,
      isShowHud: isShowHud,
      cancelToken: cancelToken,
      onsendProgress: onsendProgress,
      onReceiveProgress: onReceiveProgress,
    );
  }

  Future<HttpResponseData> put<T>(
    String path, {
    data,
    Map<String, dynamic>? queryParameters,
    bool? isShowHud,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return _request<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      isShowHud: isShowHud,
      options: checkOptions('PUT', options),
      cancelToken: cancelToken,
      onsendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );
  }

  Future<HttpResponseData> delete<T>(
    String path, {
    data,
    Map<String, dynamic>? queryParameters,
    bool? isShowHud,
    Options? options,
    CancelToken? cancelToken,
  }) {
    return _request<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      isShowHud: isShowHud,
      options: checkOptions('DELETE', options),
      cancelToken: cancelToken,
    );
  }

  Future<HttpResponseData> _request<T>(
    String url, {
    bool? isShowHud = true,
    data,
    Map<String, dynamic>? queryParameters,
    CancelToken? cancelToken,
    Options? options,
    ProgressCallback? onsendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    /// url 处理
    if (!url.startsWith('http')) {
      url = HttpConfig.baseUrl + url;
    }
    try {
      Response response = await dio.request<T>(url,
          data: data,
          queryParameters: queryParameters,
          cancelToken: cancelToken ?? _cancelToken,
          options: options,
          onSendProgress: onsendProgress,
          onReceiveProgress: onReceiveProgress);
      return response.data;
    } on DioException catch (e) {
      final eInfo = CustomHttpException.parseException(e);
      return HttpResponseData.failureFromError(eInfo);
    }
  }

  Options checkOptions(String method, Options? options) {
    options ??= Options();
    options.method = method;
    options.responseType = ResponseType.json;
    Map<String, dynamic> headers = options.headers ?? {};
    headers['device-id'] = Config.deviceId; // 设备id或者udid，保证当前设备唯一值。
    if (Platform.isAndroid) {
      headers['platform'] = 'Android';
      headers['model'] = Config.deviceModel; // 设备型号
    } else {
      headers["platform"] = "iOS";
      headers['model'] = Config.deviceModel; // 设备型号
    }
    headers['pkg'] = Config.packageName; // 包名
    headers['ver'] = Config.version; // 版本 例如1.0.0，读取实际配置的版本号
    headers['p_ver'] = Config.buildNumber; // build number
    headers['kst'] = '1'; // 固定传1
    headers['sys_lan'] = 'en'; // 手机系统语言 如英文en
    headers['lang'] = 'en'; // 手机系统语言 如英文en
    headers['Authorization'] =
        'Bearer${LYLoginInfoManager.getInstance.loginModel?.token}'; //
    options.headers = headers;
    debugPrint("==headers==$headers");

    return options;
  }
}
